package beans;

import java.io.IOException;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.view.facelets.FaceletContext;
import javax.servlet.http.HttpServletRequest;

import utils.Codification;
import utils.UsertypeDAORemote;
import controller.LoginRemote;
import dtos.UserDTO;

@ManagedBean(name = "userLoginBean")
@SessionScoped
public class UserLoginBean implements Serializable {
	// <f:event listener="#{userLoginBean.verifyUserLoged}"
	// type="preRenderView"></f:event>
	@EJB
	private LoginRemote loginRemote;

	@EJB
	private UsertypeDAORemote usertypeDAO;

	private ResourceBundle bundle = ResourceBundle.getBundle(
			"languageSettings.language", FacesContext.getCurrentInstance()
					.getViewRoot().getLocale());

	@ManagedProperty(value = "#{userDTO}")
	private UserDTO userDTO;

	@ManagedProperty("#{onlineUsers}")
	private OnlineUsers onlineUsers;

	@PostConstruct
	public void init() {
		// System.out.println("ApplicationContainer injected: " + onlineUsers);
		System.out.println(userDTO);
		// userDTO.setId(0);
	}

	public void setOnlineUsers(OnlineUsers onlineUsers) {
		this.onlineUsers = onlineUsers;
	}

	private static final long serialVersionUID = -2425742236692015992L;

	private String erorr;
	private String retypedPassword;
	private String passwordModify;

	private String userLoginBean_wrongDataInput = bundle
			.getString("Beans_beans_userLoginBean_wrongDataInput");
	private String userLoginBean_passwordMismatch = bundle
			.getString("Beans_beans_userLoginBean_passwordMismatch");
	private String userLoginBean_accountInactive = bundle
			.getString("Beans_beans_userLoginBean_accountInactive");

	public String getErorr() {
		return erorr;
	}

	public void setErorr(String erorr) {
		this.erorr = erorr;
	}

	public String getRetypedPassword() {
		return retypedPassword;
	}

	public void setRetypedPassword(String retypedPassword) {
		this.retypedPassword = retypedPassword;
	}

	public UserDTO getUserDTO() {
		return userDTO;
	}

	public void setUserDTO(UserDTO userDTO) {
		this.userDTO = userDTO;
	}

	public String getPasswordModify() {
		return passwordModify;
	}

	public void setPasswordModify(String passwordModify) {
		this.passwordModify = passwordModify;
	}

	/**
	 * This method creates a new userDTO on session and verify if the data input
	 * is correct
	 * 
	 * 
	 * @return a String containing the next page location
	 */

	public String verifyUser() {
		System.out.println("verifyUser called");
		if (userDTO.getId() != 0) {
			System.out.println("already logged in, logging out");
			logout();
		}
		FacesContext fc = FacesContext.getCurrentInstance();
		userDTO = (UserDTO) fc.getExternalContext().getSessionMap()
				.get("userDTO");
		String page = "";
		System.out.println("user-ul de la intrare este " + userDTO.getName());
		String passwordNecodificat = userDTO.getPassword();
		System.out.println("password nemodificat este " + passwordNecodificat);
		userDTO.setPassword(new Codification().md5(passwordNecodificat));
		Properties prop = new Properties();
		try {
			prop.load(getClass()
					.getResourceAsStream("/userSettings/user.properties"));
		} catch (IOException e) {

			e.printStackTrace();
		}
		String ending = prop.getProperty("passwordEnding");
		String userLoginState = loginRemote.verifyUser(getUserDTO(), ending);

		switch (userLoginState) {
		case "Pending":
			page = "passwordSet.xhtml";
			this.userDTO.setPassword(null);
			setErorr(null);
			break;
		case "Insucces":
			page = null;
			setErorr(userLoginBean_wrongDataInput);
			break;
		case "Pasword Mismatch":
			page = null;
			setErorr(userLoginBean_passwordMismatch);
			break;
		case "Account inactiv":
			page = null;
			setErorr(userLoginBean_accountInactive);
			break;
		default:
			page = chooseUser(userLoginState, ending);
			setErorr("");
			break;
		}
		return page;
	}

	/**
	 * This method selects the next page address from type of user that's logged
	 * 
	 * @param type
	 *            - a String that represents the user type
	 * @return the next page location
	 */
	public String chooseUser(String type, String ending) {
		String page = "";
		System.out.println("logged in user:" + " " + userDTO.getUsername()
				+ userDTO.getPassword());
		if (userDTO.getId() == 0) {
			System.out.println("getting user");
			userDTO = loginRemote.setUser(getUserDTO());
			HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext
					.getCurrentInstance().getExternalContext().getRequest();
			String remoteIp = httpServletRequest.getRemoteAddr();
			if (remoteIp.equals("127.0.0.1")) {
				try {
					userDTO.setIp(InetAddress.getLocalHost().getHostAddress());
				} catch (UnknownHostException e) {
					userDTO.setIp(remoteIp);
				}
			} else {
				userDTO.setIp(remoteIp);
			}
			System.out.println("IP: " + userDTO.getIp());
			userDTO.setStatus("Available");
			System.out.println(userDTO.toString());
			FacesContext.getCurrentInstance().getExternalContext()
					.getSessionMap().put("loggedUser", userDTO);
			onlineUsers.addUserToMonitor(this.userDTO);

		}
		switch (type) {
		case "Admin":
			/* aici da titlul paginei principale a adminului */
			page = "admin/mainAdmin.xhtml";
			setErorr(null);
			break;
		case "Office Manager":
			/* aici da titlul paginei principale a office managerului */
			page = "manager/mainManager.xhtml";
			setErorr(null);
			break;
		case "User":
			/* aici da titlul paginei principale a user-ului */
			page = "user/mainUser.xhtml";
			setErorr(null);
			break;
		case "Tech Guy":
			/* aici da titlul paginei principale a tech Guy-ului */
			setErorr(null);
			page = "tech/mainTech.xhtml";
			break;
		default:
			setErorr(null);
		}

		System.out.println("page is: " + page);
		return page;
	}

	/**
	 * 
	 * @return the next page location in case that the password is changed
	 *         correctly
	 */
	public String changePassword() {
		String page = "";
		if (!(passwordModify.equals(retypedPassword))) {
			setErorr(userLoginBean_passwordMismatch);
			this.userDTO.setPassword("");
			setRetypedPassword("");

		} else {
			userDTO.setPassword(getPasswordModify());
			// setRetypedPassword(new Codification().md5(getRetypedPassword()));
			System.out.println("parola pe care o trimit este "
					+ userDTO.getPassword());
			setUserDTO(loginRemote.changePassword(userDTO, retypedPassword));
			try {
				userDTO.setIp(InetAddress.getLocalHost().getHostAddress());
			} catch (UnknownHostException e) {
				e.printStackTrace();
			}
			userDTO.setStatus("Available");
			System.out.println(userDTO.toString());
			FacesContext.getCurrentInstance().getExternalContext()
					.getSessionMap().put("loggedUser", userDTO);
			onlineUsers.addUserToMonitor(this.userDTO);
			page = chooseUser(loginRemote.getUserType(userDTO), null);
		}
		return page;

	}

	public String toLogin() {
		System.out.println("in logout intra");
		logout();
		return "/login.xhtml?faces-redirect=true";
	}

	/**
	 * This method return users to the login page in case that the login page is
	 * skipped
	 */
	public void verifyA() {
		FacesContext fc = FacesContext.getCurrentInstance();
		UserDTO ud = (UserDTO) fc.getExternalContext().getSessionMap()
				.get("userDTO");
		ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler) fc
				.getApplication().getNavigationHandler();
		if (ud != null) {
			if (ud.getId() == 0)
				nav.performNavigation("login.xhtml");
		}
	}

	/**
	 * This method verify if a user is already on session and if exists create
	 * logout for him
	 * http://localhost:8080/ResourceManagerWebClient/user/mainUser.xhtml
	 */
	public void verifyUserLogged(String pageType) {
		System.out.println("verify user logged");
		UserDTO loggedU = (UserDTO) FacesContext.getCurrentInstance()
				.getExternalContext().getSessionMap().get("loggedUser");
		System.out.println("verify logged " + loggedU);
		String myPath = ((HttpServletRequest) FacesContext.getCurrentInstance()
				.getExternalContext().getRequest()).getContextPath()
				+ "/login.xhtml";
		System.out.println(myPath);
		
		if (loggedU == null || loggedU.getId() == 0) {
			System.out.println("not logged");
			// redirect to login
			try {
				logout();
				setErorr("Unauthorized access!");
				FacesContext.getCurrentInstance().getExternalContext()
						.redirect(myPath);
			} catch (IOException e) {
				System.out.println("Exception at redirect");
				e.printStackTrace();
			}
		} else {
			String type = usertypeDAO.getAllUsertypesByUserId(loggedU.getId())
					.getName();
			System.out.println("logged as type: " + type);
			// logout and redirect to login
			if (!type.equals(pageType)) {
				try {
					// redirect to login
					logout();
					setErorr("Unauthorized access!");
					System.out.println("incorrect user type, redirecting");
					FacesContext.getCurrentInstance().getExternalContext()
							.redirect(myPath);
				} catch (IOException e) {
					System.out.println("Exception at redirect");
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * This method is called on logout and set the end time for current user and
	 * set a temporary empty user on session
	 */
	public void logout() {
		loginRemote.setEndTime(userDTO);
		onlineUsers.removeUserFromMonitor(userDTO);
		FacesContext.getCurrentInstance().getExternalContext()
				.invalidateSession();
		setErorr(null);
	}

	/**
	 * This method is called before the page is destroyed without logout
	 */
	@PreDestroy
	public void endSession() {
		logout();
	}

    public UserDTO getLoggedUser() {
        return (UserDTO) FacesContext.getCurrentInstance()
                .getExternalContext().getSessionMap().get("loggedUser");
    }

    public void setLoggedUser(UserDTO userDTO) {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("loggedUser", userDTO);
    }
}
